#! /usr/bin/perl

use FindBin qw($Bin);
use lib "$Bin/../lib";  

###################################################################
# CONFIGURATION
# the path to your maude 2 binary
$maude = "maude.linux";
###################################################################

$btt="$Bin/bttFsm2.maude";
$program="ftLTLtmp";

@predicates =();
@predicate2expr = ();
$formula="";
@fncts = ();
@events = ();
$flag = 0;

while (<>){
    s/\/\/.*//;
    if ($flag == 0) {
	if (/Predicate\s+(\S+)\s*\:(.*)\;/) {
	    $predicates[$#predicates+1] = $1 ;
	    $predicate2expr{$1} = "($2)";	
	} else {
	    if (/Event\s+(\S+)\s*\:(.*)\;/) {
		$fncts[$#fncts+1] = $1 ;
	    } else{
		if (/Formula\s*\:/) {
		    s/;//g;
		    s/Formula\s*\://;
		    s/\(\*\)/{*}/g;
		    s/\)s/}s/g;
                    s/\)w/}w/g;
	            s/\!|\/\\|\\\/|\-\>|\<\-\>|\+\+|\{\*\}|\[\*\]|\<\*\>|\[|\}s|\}w/ $& /g;
	            s/\s+/ /g;
	            for ($i = 0; $i <= $#fncts; $i ++){
			if (/start\($fncts[$i]\)/){
			    $events[$#events+1] = "\$start-$fncts[$i]";
			    s/start\($fncts[$i]\)/\$start\-$fncts[$i]/g;
			}
			if (/end\($fncts[$i]\)/){
			    $events[$#events+1] = "\$end-$fncts[$i]";
			    s/end\($fncts[$i]\)/\$end\-$fncts[$i]/g;
			}
			if (/(.)$fncts[$i]/){
			    $tmp = $1;
			    if (! ($tmp =~ /\-/)){
				$events[$#events+1] = "\$end-$fncts[$i]";
				s/$tmp$fncts[$i]/$tmp\$end\-$fncts[$i]/g;
			    }
			}
	            }
	            $formula=$_;
	            $flag = 1;
                 }
            }
	}
     } else {
        if ((/Violation\sHandler/) || (/Validation\sHandler/) || (/Violation\shandler/) || (/Validation\shandler/)){
	    $flag = 0;
        } else { 
	    s/;//g;
	    s/\(\*\)/{*}/g;
	    s/\)s/}s/g;
            s/\)w/}w/g;
            s/\!|\/\\|\\\/|\-\>|\<\-\>|\+\+|\{\*\}|\[\*\]|\<\*\>|\[|\}s|\}w/ $& /g;
            s/\s+/ /g;
            for ($i = 0; $i <= $#fncts; $i ++){
		if (/start\($fncts[$i]\)/){
		    $events[$#events+1] = "\$start-$fncts[$i]";
		    s/start\($fncts[$i]\)/\$start\-$fncts[$i]/g;
		}
		if (/end\($fncts[$i]\)/){
		    $events[$#events+1] = "\$end-$fncts[$i]";
		    s/end\($fncts[$i]\)/\$end\-$fncts[$i]/g;
		}
		if (/(.)$fncts[$i]/){
		    $tmp = $1;
		    if (! ($tmp =~ /\-/)){
			$events[$#events+1] = "\$end-$fncts[$i]";
			s/$tmp$fncts[$i]/\$end\-$fncts[$i]/g;
		    }
		}
            }
	    $formula = $formula.$_; 
	}
     }
}

$pred = "@predicates" ;
$eve = "@events";

#generate the required maude module
open(FILE, "> $program.maude") ;
print FILE "in $btt \n\n" ;
print FILE "fmod TEST is pr BTT-FSM . \n" ;
print FILE "ops $pred $eve : -> Atom . \n" ;
print FILE "op formula : -> Formula . \n \n" ;
print FILE "eq formula = $formula . \n" ;
print FILE "endfm \n \n" ;
print FILE "red bttFsm(formula) . \n\n quit" ;
close FILE ;

system("$maude $program.maude > $program.mout") ; 

open (outfile, "$program.mout");
   
# Matching the output statement
while (<outfile>){
   if (/^result\s*BttFsm:/){
	$f = $_ ;
        while (<outfile>){
	   if (!(/^Bye/)){
              $f = $f.$_ ;
            }
       }   
   }
}
 
close outfile ;

if (!(defined($f))){
    print "Future Time LTL: Cannot deal with the logic input.\n";
    unlink "$program.maude";
    unlink "$program.mout";
    exit 1;
}

$f=~s/result\s*BttFsm://g ; $f=~s/\n// ; $f=~s/(\s)+/ /g ; $f=~s/^(\s)+//;
@f = split(/,/,$f) ;

for($i=0;$i<=$#f;$i++) {
 ($btt[$i]) = ($f[$i] =~ m|^\s*[\(]?\d\[(.*?)\].*?$|ms) ; 
  $btt[$i] =~ s/\bt\b/-1/ms;
  $btt[$i] =~ s/\bf\b/-2/ms;
  $btt[$i] = " $btt[$i]";
for ( $ii = 0 ; $ii <= $#predicates ; $ii ++) {
    $btt[$i] =~ s/(\W)$predicates[$ii]/$1$predicate2expr{$predicates[$ii]}/g;
}
}

$state = "\$state" ;
print "// Declaration \n int $state = 1; \n";
for ($i = 0; $i <= $#events; $i ++){
    $item = $events[$i];
    $item =~ s/\$(.+)\-(.+)/$1($2)/g;
    print "fnct $events[$i] = $item;\n";
}

print "// Monitoring body \n" ;
#print "$extract \n" ;
print "switch($state) { \n ";
for($i=0;$i<=$#f;$i++) {
  $j = $i + 1 ; 
  print "case $j: \n $state =$btt[$i] ; \n break ; \n" ;   
}
print "} \n \n" ;
print "// Failure condition \n $state == -2 \n\n ";
print "// Success condition \n $state == -1 \n\n "; 

unlink "$program.maude";
unlink "$program.mout";
